
#include "report.h"
extern int flag;

extern struct pointMsg point;   // 存放点表信息
extern MQTTClient client;       // 客户端
extern struct std_node *addr;   // 存放共享内存的地址
extern int *total;              // 指向前四个字节的总数
extern struct std_node *data_p; // 指向四个字节后的第一个结构体
extern char *errmsg;            // 接收表错误信息
extern sqlite3 *db;
char str[20] = {0};
/**
 * @brief Create a database object
 *
 * @param db
 */
int create_database()
{

    if (sqlite3_open("node.db", &db) < 0)
    {
        fprintf(stderr, "sqlite3_open err:%s\n", sqlite3_errmsg(db));
        return -1;
    }
    if (sqlite3_exec(db, "create table mydata(time int,key int ,data char,primary key (time,key));", NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "sqlite3_open err:%s\n", errmsg);
    }
    printf("database create success\n");
    return 0;
}
/**
 * @brief 解析点表，
 *
 * @param ret
 */
int json_init(struct mqtt *ret)
{

    int fp = open("/home/yqj/hq_plat/res/node.json", O_RDWR);
    if (fp == -1)
    {
        perror("open err\n");
    }
    int size = lseek(fp, 0L, SEEK_END);
    printf("size=%d\n", size);
    lseek(fp, 0L, SEEK_SET);
    char *data = (char *)malloc(2300);
    if (read(fp, data, size) == -1)
    {
        perror("read err\n");
        return -1;
    }
    printf("file size:%s\n", data);

    cJSON *json = cJSON_Parse(data);
    cJSON *tmp = cJSON_GetObjectItem(json, "report");
    cJSON *type = cJSON_GetObjectItem(tmp, "type");
    if (type->valueint == 2)
    {
        cJSON *time = cJSON_GetObjectItem(tmp, "period"); // type==2时，定时上报，拿到period的值
        ret->period = time->valueint;
    }
    ret->type = type->valueint;
    tmp = cJSON_GetObjectItem(json, "mqtt_server");
    type = cJSON_GetObjectItem(tmp, "addr");
    strcpy(ret->ip, type->valuestring);
    type = cJSON_GetObjectItem(tmp, "port");
    ret->port = type->valueint;

    return 0;
}

void refresh_report(MQTTClient client, struct std_node *ret[2])
{
    LOGD("-------------------刷新上报---------------------------");

    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    while (1)
    {
        if (flag == 1)
        {
            cJSON *js_new = cJSON_CreateObject();
            cJSON_AddNumberToObject(js_new, "type", 1);
            cJSON_AddNumberToObject(js_new, "result", 0);
            cJSON *array = NULL;
            cJSON_AddItemToObject(js_new, "data", array = cJSON_CreateArray());
            for (int i = 0; i < 3; i++)
            {
                memset(str, 0, 20);
                cJSON *array_obj = NULL;
                cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                cJSON_AddNumberToObject(array_obj, "key", ret[0][i].key);
                switch (ret[0][i].type)
                {
                case 1:
                    sprintf(str, "%d", ret[0][i].new_val.b_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                case 2:
                    sprintf(str, "%d", ret[0][i].new_val.i_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                case 3:
                    sprintf(str, "%.2f", ret[0][i].new_val.f_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                }
            }

            for (int i = 0; i < 5; i++)
            {
                memset(str, 0, 20);
                cJSON *array_obj = NULL;
                cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                cJSON_AddNumberToObject(array_obj, "key", ret[1][i].key);
                switch (ret[1][i].type)
                {
                case 1:
                    sprintf(str, "%d", ret[1][i].new_val.b_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                case 2:
                    sprintf(str, "%d", ret[1][i].new_val.i_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                case 3:
                    sprintf(str, "%.2f", ret[1][i].new_val.f_val);
                    cJSON_AddStringToObject(array_obj, "val", str);
                    break;
                }
            }

            pubmsg.payload = cJSON_Print(js_new);
            pubmsg.payloadlen = (int)strlen(cJSON_Print(js_new));
            pubmsg.qos = QOS;
            pubmsg.retained = 0;
            MQTTClient_publishMessage(client, DATATOPIC, &pubmsg, &token);
            printf("%s\n", cJSON_Print(js_new));
            cJSON_Delete(js_new);
            flag = 0;
        }
        sleep(0);
    }
}
void period_report(MQTTClient client, struct std_node *ret[2], int time)
{
    LOGD("-------------------定时上报---------------------------\n");
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    while (1)
    {
        cJSON *js_new = cJSON_CreateObject();
        cJSON_AddNumberToObject(js_new, "type", 1);
        cJSON_AddNumberToObject(js_new, "result", 0);
        cJSON *array = NULL;
        cJSON_AddItemToObject(js_new, "data", array = cJSON_CreateArray());
        for (int i = 0; i < 3; i++)
        {
            memset(str, 0, 20);
            cJSON *array_obj = NULL;
            cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
            cJSON_AddNumberToObject(array_obj, "key", ret[0][i].key);
            switch (ret[0][i].type)
            {
            case 1:
                sprintf(str, "%d", ret[0][i].new_val.b_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            case 2:
                sprintf(str, "%d", ret[0][i].new_val.i_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            case 3:
                sprintf(str, "%.2f", ret[0][i].new_val.f_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            }
        }

        for (int i = 0; i < 5; i++)
        {
            memset(str, 0, 20);
            cJSON *array_obj = NULL;
            cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
            cJSON_AddNumberToObject(array_obj, "key", ret[1][i].key);
            switch (ret[1][i].type)
            {
            case 1:
                sprintf(str, "%d", ret[1][i].new_val.b_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            case 2:
                sprintf(str, "%d", ret[1][i].new_val.i_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            case 3:
                sprintf(str, "%.2f", ret[1][i].new_val.f_val);
                cJSON_AddStringToObject(array_obj, "val", str);
                break;
            }
        }

        pubmsg.payload = cJSON_Print(js_new);
        pubmsg.payloadlen = (int)strlen(cJSON_Print(js_new));
        pubmsg.qos = QOS;
        pubmsg.retained = 0;
        MQTTClient_publishMessage(client, DATATOPIC, &pubmsg, &token);
        printf("%s\n", cJSON_Print(js_new));
        cJSON_Delete(js_new);
        sleep(time);
    }
}
void change_report(MQTTClient client, struct std_node *ret[2])
{
    LOGD("-------------------变化上报---------------------------\n");

    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    int change = 0;
    while (1)
    {
        cJSON *js_new = cJSON_CreateObject();
        cJSON_AddNumberToObject(js_new, "type", 1);
        cJSON_AddNumberToObject(js_new, "result", 0);
        cJSON *array = NULL;
        cJSON_AddItemToObject(js_new, "data", array = cJSON_CreateArray());
        for (int i = 0; i < 3; i++)
        {
            memset(str, 0, 20);
            switch (ret[0][i].type)
            {
            case 1:
                if (ret[0][i].new_val.b_val != ret[0][i].old_val.b_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[0][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[0][i].new_val.b_val);
                    ret[0][i].new_val.b_val = ret[0][i].old_val.b_val;
                    change = 1;
                }
                break;
            case 2:
                if (ret[0][i].new_val.i_val != ret[0][i].old_val.i_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[0][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[0][i].new_val.i_val);
                    ret[0][i].new_val.i_val = ret[0][i].old_val.i_val;
                    change = 1;
                }
                break;
            case 3:
                if (ret[0][i].new_val.f_val != ret[0][i].old_val.f_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[0][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[0][i].new_val.f_val);
                    ret[0][i].new_val.f_val = ret[0][i].old_val.f_val;
                    change = 1;
                }
                break;
            }
        }

        for (int i = 0; i < 5; i++)
        {
            memset(str, 0, 20);
            switch (ret[1][i].type)
            {
            case 1:
                if (ret[1][i].new_val.b_val != ret[1][i].old_val.b_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[1][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[1][i].new_val.b_val);
                    ret[1][i].new_val.b_val = ret[1][i].old_val.b_val;
                    change = 1;
                }
                break;
            case 2:
                if (ret[1][i].new_val.i_val != ret[1][i].old_val.i_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[1][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[1][i].new_val.i_val);
                    ret[1][i].new_val.i_val = ret[1][i].old_val.i_val;
                    change = 1;
                }
                break;
            case 3:
                if (ret[1][i].new_val.f_val != ret[1][i].old_val.f_val)
                {
                    cJSON *array_obj = NULL;
                    cJSON_AddItemToArray(array, array_obj = cJSON_CreateObject());
                    cJSON_AddNumberToObject(array_obj, "key", ret[1][i].key);
                    cJSON_AddNumberToObject(array_obj, "val", ret[1][i].new_val.f_val);
                    ret[1][i].new_val.f_val = ret[1][i].old_val.f_val;
                    change = 1;
                }
                break;
            }
        }
        if (change == 1)
        {
            printf("变化值=%d\n", change);
            pubmsg.payload = cJSON_Print(js_new);
            pubmsg.payloadlen = (int)strlen(cJSON_Print(js_new));
            pubmsg.qos = QOS;
            pubmsg.retained = 0;
            MQTTClient_publishMessage(client, DATATOPIC, &pubmsg, &token);
            printf("%s\n", cJSON_Print(js_new));
            change = 0;
        }
        cJSON_Delete(js_new);
        sleep(5);
    }
}

/* 	    para：   传递给回调函数的参数
        f_num：  记录中包含的字段数目(id name score)
                 相当于有多少列;
        f_value：包含每个字段值的指针数组
        f_name：包含每个字段名称的指针数组
 */
int historyCallback(void *para, int f_num, char **f_value, char **f_name)
{
    cJSON *root = (cJSON *)para;
    cJSON *tmp = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "NULL", tmp);
    cJSON_AddStringToObject(tmp, "time", f_value[0]);
    cJSON_AddStringToObject(tmp, "val", f_value[2]);
    return 0;
}

void history_report()
{
    char *str = NULL;

    cJSON *root = cJSON_CreateObject();
    cJSON *array = cJSON_CreateArray();
    cJSON_AddNumberToObject(root, "type", 4);
    cJSON_AddNumberToObject(root, "key", 301);
    
    cJSON_AddNumberToObject(root, "result", 0);
    cJSON_AddItemToObject(root, "data", array);

    char sql[128] = {0};
    sprintf(sql, "select * from mydata where key=101 and time>1666482618 and time <1666582621;");
    if (sqlite3_exec(db, sql, historyCallback, array, &errmsg) != 0)
    {
        fprintf(stderr, "insert err:%s\n", errmsg);
    }
    str = cJSON_Print(root);
    mqttSend(str);
    free(str);
    cJSON_Delete(root);
}
/**
 * @brief 初始化共享内存
 *
 * @param para
 * @param name
 * @param size
 * @return void*
 */
void *myshm_init(struct shm_param *para, char *name, int size)
{
    int ret = shm_init(para, name, size);
    if (ret < 0)
    {
        return NULL;
    }
    void *addr = shmat(para->id, NULL, 0);
    if (addr == (void *)-1)
    {
        para->addr = NULL;
    }
    else
    {
        para->addr = addr;
    }
    return para->addr;
}
